<?php
/**
 * 肤质检测记录表
 * Author: Zeon
 * Date: 2018/4/4
 * Created by Panxsoft.
 */

namespace App\Models\Store;

use App\Models\Admin\StoreAdmin;
use App\Models\Concerns\ScopeFilterable;
use App\Models\Customer\DeviceAccount;
use App\Models\OpenWechat\Authorizer;
use App\Models\OpenWechat\WechatUser;
use App\Models\Panx\SkinDetector;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;

/**
 * Class SkinRecord
 *
 * @property int id
 * @property string store_name
 * @property string store_img
 * @property int $wechat_user_id
 * @property int $device_account_id
 * @property int skin_detector_id
 * @property int $store_admin_id
 * @property Carbon $created_at
 *
 * @property-read Store $store
 * @property-read wechatUser wechatUser
 * @property-read StoreAdmin $storeAdmin
 * @property-read DeviceAccount deviceAccount
 * @property-read CamSkinRecord[]|Collection camSkinRecords - 废弃
 * @property-read WaxSkinRecord[]|Collection waxSkinRecords
 * @property-read HmSkinRecord[]|Collection hmSkinRecords
 *
 * @property-write WaxSkinRecord[]|Collection wax_skin_records
 * @property-write string skin_data - 肤质数据？
 * @property string store_id
 *
 * @method static self filterStoreKeyword(?string $keyword)
 *
 * @mixin Builder
 */
class SkinRecord extends Model
{
    use ScopeFilterable;

    const WAX = SkinDetector::ID_WAX;
    const HM = SkinDetector::ID_HM;

    protected $table = 'skin_records';

    protected static $unguarded = true;

    protected $casts = [
        'skin_detector_id' => 'int',
        'wechat_user_id' => 'int',
        'store_admin_id' => 'int',
        'device_account_id' => 'int',
    ];

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function store()
    {
        return $this->belongsTo(Store::class, 'store_id', 'id');
    }
    
    public function wechatUser()
    {
        return $this->belongsTo(WechatUser::class, 'wechat_user_id', 'id');
    }

    public function storeAdmin()
    {
        return $this->belongsTo(StoreAdmin::class, 'store_admin_id', 'id');
    }

    public function skinDetector()
    {
        return $this->belongsTo(SkinDetector::class, 'skin_detector_id', 'id');
    }

    public function deviceAccount()
    {
        return $this->belongsTo(DeviceAccount::class, 'device_account_id', 'id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function waxSkinRecords()
    {
        return $this->hasMany(WaxSkinRecord::class, 'skin_record_id', 'id')
            ->whereIn('itemsid',WaxSkinRecord::ITEMSID_ALL);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function camSkinRecords()
    {
        return $this->hasMany(CamSkinRecord::class, 'skin_record_id', 'id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany |HmSkinRecord
     */
    public function hmSkinRecords()
    {
        return $this->hasMany(HmSkinRecord::class, 'skin_record_id', 'id');
    }

    /**
     * @deprecated
     *
     * 多态多对多主要应用于 tag 对就多种类型表， 多种类型表 ( 如 Video / Article 等 ) 中条目同时有多个 tags，
     * 才比较有用. 这里 一个 skinRecord 对应多个不同类型 CamSkinRecords/HmSkinRecords/WaxSkinRecord，
     * 但不同类型的 CamSkinRecords / HmSkinRecords / WaxSkinRecord 并不对应多个 skinRecords 所以不太适用
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function morphCamSkinRecords()
    {
        return $this->morphedByMany(CamSkinRecord::class, 'skin_recordable');
    }

    /**
     * 微信用户最近一次对应检测仪类型的 SkinRecord[]
     *
     * @example
     *  self::latestWechatUsersTypeSkinRecords([37, 40], 3) =>
     * Illuminate\Database\Eloquent\Collection {
     *     all: [
     *         App\Models\Store\SkinRecord { <- 最近一次的 skin_detector_id 是 3 的 SkinRecord
     *             id: 119,
     *             wechat_user_id: 37,
     *         },
     *         App\Models\Store\SkinRecord {
     *             id: 113,
     *             wechat_user_id: 40,
     *         },
     *     ],
     * }
     *
     * @param int[] $wechat_user_ids
     * @param $skin_detector_id
     *
     * @return Collection|SkinRecord[]
     */
    public static function latestWechatUsersTypeSkinRecords(array $wechat_user_ids,
                                                            int $skin_detector_id): Collection
    {
        return (new self)
            ->whereIn('wechat_user_id', $wechat_user_ids)
            ->where('skin_detector_id', $skin_detector_id)
            ->selectRaw('max(id) as id, wechat_user_id')
            ->groupBy('wechat_user_id')
            ->get();
    }

    /**
     * @see latestWechatUsersTypeSkinRecords - 只是按店铺 id[] 过滤所有 wechatUsers 最后一次 skinRecord[]
     *
     * @param int[] $store_ids
     * @param int $skin_detector_id
     *
     * @return Collection|self[]
     */
    public static function latestStoresWechatUsersTypeSkinRecords(array $store_ids,
                                                                  int $skin_detector_id): Collection
    {
        $wechat_user_ids = StorePivotWechatUser::storesWechatUsersIds($store_ids);

        return (new self)
            ->whereIn('store_id', $store_ids)
            ->whereIn('wechat_user_id', $wechat_user_ids)
            ->where('skin_detector_id', $skin_detector_id)
            ->selectRaw('max(id) as id, wechat_user_id, store_id')
            ->groupBy('wechat_user_id', 'store_id')
            ->get();
    }

    /**
     * @used-by filterStoreKeyword - 根据店铺关键字过滤测肤记录
     *
     * @param Builder $builder
     * @param $keyword
     *
     * @return Builder
     */
    public function scopeFilterStoreKeyword(Builder $builder, $keyword)
    {
        if (! $keyword) return $builder;

        $store_ids = (new Store)
            ->columnsKeywordOrLike(['name', 'phone'], $keyword)
            ->pluck('id');

        return $builder->whereIn('store_id', $store_ids);
    }

    public function isHuiMei(): bool
    {
        return $this->skin_detector_id === self::HM;
    }

    public function isWax(): bool
    {
        return $this->skin_detector_id === self::WAX;
    }

    public function getAuthor(): ?Authorizer
    {
        return $this->store->customer->authorizer ?? null;
    }

    /**
     * @return bool
     */
    public function isBonusUseMagicMirrorAuthor(): bool
    {
        $author_id = $this->getAuthor()->id ?? null;

        return $author_id === Authorizer::ID_MAGIC_MIRROR;
    }

    /**
     * @return bool
     */
    public function isBonusUseAliPay(): bool
    {
        return ! $this->isBonusUseMagicMirrorAuthor();
    }

    /**
     * @param $type_skin_record_id
     * @return int
     */
    public function isHasWaxOrHmSkinRecords($type_skin_record_id)
    {
        $skin_detector_id = $this->skin_detector_id;

        if ($skin_detector_id === SkinDetector::ID_WAX) {
            $data = $this->waxSkinRecords;
        } else if ($skin_detector_id === SkinDetector::ID_HM) {
            $data = $this->hmSkinRecords;
        } else {
            $data = $this->camSkinRecords;
        }

        $count = $data->where('id', $type_skin_record_id)
            ->count();

        return $count;
    }

    /**
     * @param $type_skin_record_id
     * @return mixed
     */
    public function getWaxOrHmSkinRecordById($type_skin_record_id)
    {
        $skin_detector_id = $this->skin_detector_id;

        if ($skin_detector_id === SkinDetector::ID_WAX) {
            $data = $this->waxSkinRecords;
        } else if ($skin_detector_id === SkinDetector::ID_HM) {
            $data = $this->hmSkinRecords;
        } else {
            $data = $this->camSkinRecords;
        }

        $skin_record = $data->where('id', $type_skin_record_id)
            ->first();

        return $skin_record;
    }
}
